/**
 *  主游戏逻辑脚本
 */

var com = require('Common');

cc.Class({
  extends: cc.Component,

  properties: {
    restartView: cc.Node, // 重新开始层
    tip: cc.Node, // 提示
    player: cc.Node, // 游戏角色节点
    scoreLabel: cc.Label, // 分数文本
    scoreLabelR: cc.Label, // 复活界面分数文本
    nodeView: cc.Node, // 台阶和金币层
    stairView: cc.Node, // 台阶层
    stair: cc.Prefab, // 台阶预制
    stairCount: 0, // 台阶数量
    otherStairCount: 30000, // 障碍台阶数量
    // 移动持续时间
    moveDuration: 0.2,
    moveDuration2: 0.1,
    // 台阶宽高
    stairWidth: 240,
    stairHeight: 180,
    // 前一个台阶定位
    preStairX: 0,
    preStairY: 0,
    otherStairs: [cc.Prefab], // 障碍台阶数组
    time: 0, // 运行时间
    stairDownSecond: 4,
    gameOverSecond: 0.33,
    coinView: cc.Node, // 金币层
    coinPrefab: cc.Prefab, // 金币预制
  },

  onLoad() {
    // 初始化数据
    this.stairDownSecond = com.stairDownSecond;
    this.gameOverSecond = com.gameOverSecond;
    this.scoreLabel.string = cc.sys.localStorage.getItem("score");
    this.player.zIndex = 1;
    this.scoreLabel.node.zIndex = 10;

    if (com.isWechatGame) com._hideBannerAd(); // 游戏中不显示banner广告

    // 判断是否从首页进入,控制显示tip
    if (com.first_play) {
      this.tip.active = true;
    }

    // 背景音乐控制
    var bgm = cc.find('Bgm').getComponent('bgm');
    if (com.bgm_play) {
      bgm.play();
    }

    // 碰撞管理器
    var manager = cc.director.getCollisionManager();
    manager.enabled = false;

    this.setInputControl();

    // 生成8个初始台阶
    for (var i = 0; i < 8; i++) {
      this.newStair();
    }

    cc.director.preloadScene("Over")
  },

  // 监听玩家点击控制
  setInputControl: function () {
    this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this)
  },

  // 角色向左跳
  playerMoveLeft: function () {
    // 角色上下跳动,然后台阶父节点整体右移
    var goL1 = cc.moveTo(this.moveDuration2, cc.v2(0, -320));
    var goL2 = cc.moveTo(this.moveDuration2, cc.v2(0, -400));
    var sque = cc.sequence(goL1, goL2);
    this.player.runAction(sque);
    this.player.scaleX = -2; // 角色朝向左
    var goAction = cc.moveBy(0.2, cc.v2(this.stairWidth / 2, -120));
    this.nodeView.runAction(goAction);
  },

  //角色向右跳
  playerMoveRight: function () {
    // 角色上下跳动,然后台阶父节点整体左移
    var goR1 = cc.moveTo(this.moveDuration2, cc.v2(0, -320));
    var goR2 = cc.moveTo(this.moveDuration2, cc.v2(0, -400));
    var sque = cc.sequence(goR1, goR2);
    this.player.runAction(sque);
    this.player.scaleX = 2; // 角色朝向右
    var goAction = cc.moveBy(0.2, cc.v2(-this.stairWidth / 2, -120));
    this.nodeView.runAction(goAction);
  },

  update(dt) {
    if (com.gameIsStart) {
      this.time += dt; // dt为每一帧执行的时间，把它加起来等于运行了多长时间
      if (this.time >= this.stairDownSecond) {
        cc.log("stairDownSecond" + this.stairDownSecond);
        this.downStair();
        this.time = 0;  //每达到stairDownSecond的值后重置时间为0，以达到循环执行  
      }
    }
  },

  //生成一个台阶(开始游戏前,生成新的台阶方法)
  newStair: function () {
    this.stairCount += 1; // 数量加一
    var newStair = cc.instantiate(this.stair); // 从Prefab实例化出新台阶
    this.stairView.addChild(newStair, -1); // 添加子节点
    var stairPosition = this.stairPosition() // 获取台阶定位
    newStair.setPosition(stairPosition); // 设置台阶节点在父节点坐标系中的位置。
  },

  //台阶生成带上动画效果(开始游戏后,生成新的台阶方法)
  newStairUpToDown: function () {
    this.stairCount += 1;
    var newStair = cc.instantiate(this.stair);
    this.stairView.addChild(newStair, -999);
    var stairPosition = this.stairPosition();
    // 将新台阶生成在本应该在的位置的上方,然后利用下移动作移到应该在的位置,这样就形成动画效果
    newStair.setPosition(cc.v2(stairPosition.x, stairPosition.y + this.stairHeight / 2));
    var goAction = cc.moveTo(this.moveDuration2, stairPosition);
    newStair.runAction(goAction);
  },

  // 生成金币
  newCoinUpToDown: function () {
    if (this.stairCount == 1 || this.stairCount == 2) {
      return;
    }
    var coin = cc.instantiate(this.coinPrefab);
    this.coinView.addChild(coin);
    var coinPosition = cc.v2(this.preStairX, this.preStairY + 55);
    coin.setPosition(cc.v2(coinPosition.x, coinPosition.y + this.stairHeight / 2 + 55));
    var goAction2 = cc.moveTo(this.moveDuration2, coinPosition);
    coin.runAction(goAction2);
  },

  // 生成障碍台阶
  newOtherStair: function (isLeft, position) {
    // 第一个不生成
    if (this.stairCount == 1) {
      return;
    }

    // 一共有2种障碍物
    // 第一种为显示出来的怪物障碍(概率小)
    // 第二种为全透明的空白障碍,主要用来判断跳空(概率大)
    var hasOther = false;
    var randD = Math.random();

    // 生成怪物障碍台阶的概率
    if (randD < com.hinderRate) {
      hasOther = true;
    } else {
      var rand = Math.random(); // 定义金币出现概率
      if (rand < com.coinRate) {
        this.newCoinUpToDown();
      }
    }

    var count = 0;
    if (hasOther) {
      count = Math.ceil(Math.random() * 9);
    }

    var newStair = cc.instantiate(this.otherStairs[count]);

    this.otherStairCount--;

    this.stairView.addChild(newStair, this.otherStairCount);

    //如果生成的台阶在左，那障碍就在右
    if (isLeft) {
      newStair.setPosition(this.preStairX + this.stairWidth / 2, position.y + 40);
    } else {
      newStair.scaleX = -newStair.scaleX;
      newStair.setPosition(this.preStairX - this.stairWidth / 2, position.y + 40);
    }
  },

  // 台阶定位
  stairPosition: function () {
    var randX = 0;
    var randY = 0;

    var isLeft = true; // 默认定位左边
    var rand = Math.random(); // 定义随机数判断左右
    if (rand > 0.5) {
      isLeft = false;
    }

    // 判断需要定位的台阶排位
    if (this.stairCount == 1) {
      // 如果是第一个台阶,就是定位到角色下方
      randX = this.player.getPosition().x;
      randY = this.player.getPosition().y - 80;
    } else {
      // 如果不是第一个台阶,则判断左右
      if (isLeft) {
        // 左边情况,x轴为上一个台阶的x轴减一半台阶宽度
        randX = this.preStairX - this.stairWidth / 2;
        if (this.stairCount == 2) { // 如果第二个是左边,改变角色朝向
          this.player.scaleX = -2;
        }
      } else {
        // 右边情况,x轴为上一个台阶的x轴加一半台阶宽度
        randX = this.preStairX + this.stairWidth / 2;
      }
      randY = this.preStairY + 120; // y轴
    }

    var position = cc.v2(randX, randY);
    // 随机生成障碍台阶
    this.newOtherStair(isLeft, position);

    // 将当前台阶定位赋给上一个台阶定位
    this.preStairX = randX;
    this.preStairY = randY;

    // 返回定位
    return position;
  },

  // 台阶掉落逻辑
  downStair: function () {
    var childrens = this.stairView.children;
    var length = childrens.length;

    // 循环判断每一个台阶
    for (var i = 0; i < length; i++) {
      var stairPrefab = childrens[i];
      var newStair = stairPrefab.getComponent("Stair");

      if (newStair.isUsed) { // 如果台阶已经碰撞过
        if (newStair.isStanding) { // 如果角色还是站在台阶上,就让角色和台阶一起掉落
          com.gameIsStart = false;

          this.node.off(cc.Node.EventType.TOUCH_START, this.on_touch_start, this);

          var downAction = cc.moveBy(0.4, cc.v2(0, -600));
          var callback = cc.callFunc(this.gameIsOver, this);   //callFunc在动画执行完毕后调用哪个方法
          var seq = cc.sequence(downAction, callback);
          this.player.runAction(seq);

          var goAction = cc.moveBy(0.4, cc.v2(0, -600));
          var fadeAction = cc.fadeOut(0.2, 1.0);
          var spa = cc.spawn(goAction, fadeAction);
          newStair.node.runAction(spa);

        } else { // 如果角色不站在台阶上,就台阶掉落
          var goAction = cc.moveBy(0.8, cc.v2(0, -600));
          var fadeAction = cc.fadeOut(0.5, 1.0);
          var spa = cc.spawn(goAction, fadeAction);
          newStair.node.runAction(spa);
        }
      }
    }
  },

  // 游戏结束
  gameIsOver: function () {
    if (com.isWechatGame) com._showBannerAd();
    this.scoreLabelR.string = cc.sys.localStorage.getItem("score");
    this.unschedule();
    this.node.off(this);    //移除所有点击事件
    if (!com.canRevive) {
      com.handlerMaxScore();
      cc.director.loadScene("Over");
    } else {
      this.scoreLabel.node.active = false;
      this.restartView.active = true;
    }
  },

  // 用户点击监听
  onTouchStart: function (event) {
    // 游戏是否开始
    if (!com.gameIsStart) {
      com.gameIsStart = true;
    }
    this.time = 0;

    if (com.first_play) {
      com.first_play = false;
      this.tip.active = false;
    }

    let location = event.touch.getLocation();
    let locationX = location.x;
    // 判断点击位置左右,进行左右移动
    if (locationX > this.node.width / 2) {
      this.playerMoveRight();
    } else {
      this.playerMoveLeft();
    }

    // 生成台阶
    this.newStairUpToDown();

    if (this.stairDownSecond <= this.gameOverSecond) {
      this.stairDownSecond = this.gameOverSecond;
    } else {
      this.stairDownSecond -= 0.02;
    }
  },
});
